
#include "nane/SoundSystem/SoundSystemImpl_.h"
#include "nane/SoundSystem/SoundBufferImpl_.h"
#include "nane/SoundSystem/SoundSourceImpl_.h"
#include "nane/SoundSystem/SoundSource3DImpl_.h"

#include "nane/core/assert.h"

namespace nane
{
    ////////////////////////////////////////////////////////////////////////////////////////////////
    SoundSystem::Implementation::Implementation()
        : SubSystem<ISoundSystem>::Implementation("ISoundSystem")
        , contextInitialized( false )
        , updating( false )
    {

    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    SoundSystem::Implementation::~Implementation()
    {

    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    void SoundSystem::Implementation::RegisterUpdate( SoundSource::Implementation* _soundSourceImpl )
    {
        NANE_ASSERT_R( std::find(activeSources.begin(), activeSources.end(), _soundSourceImpl) == activeSources.end(), "error to register same source more than once" );
        NANE_ASSERT_R( updating == false, "error to register source while updating" );
        activeSources.push_back(_soundSourceImpl);
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    void SoundSystem::Implementation::Update( uint32 _ms )
    {
        updating = true;
        std::vector<SoundSource::Implementation*>::iterator it_end = activeSources.end();
        for( std::vector<SoundSource::Implementation*>::iterator it = activeSources.begin(); it != it_end; /*++it*/ )
        {
            if( (*it)->Update(_ms) == false )
            {
                std::swap(*it, *(it_end - 1));
                --it_end;
            }
			else
            {
                ++it;
            }
        }
        activeSources.erase(it_end, activeSources.end());
        updating = false;
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    void SoundSystem::Implementation::UnregisterUpdate( SoundSource::Implementation* _soundSourceImpl )
    {
        NANE_ASSERT_R( updating == false, "error to unregister source while updating" );
        activeSources.erase(std::remove(activeSources.begin(), activeSources.end(), _soundSourceImpl));
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    void SoundSystem::Implementation::Release( SoundBuffer::Implementation* _soundBufferImpl )
    {
        NANE_ASSERT_R( interface != NULL, "SoundSystem must be initialized" );
        NANE_ASSERT_R( this == _soundBufferImpl->creator, "SoundBuffer must be valid" );
        ISoundBuffer* soundBufferInterface = _soundBufferImpl->interface;
        delete _soundBufferImpl;
        interface->ReleaseSoundBuffer(soundBufferInterface);
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    void SoundSystem::Implementation::Release( SoundSource::Implementation* _soundSourceImpl )
    {
        NANE_ASSERT_R( interface != NULL, "SoundSystem must be initialized" );
        NANE_ASSERT_R( this == _soundSourceImpl->creator, "SoundSource must be valid" );
        ISoundSource* soundSourceInterface = _soundSourceImpl->interface;
        delete _soundSourceImpl;
        interface->ReleaseSoundSource(soundSourceInterface);
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    void SoundSystem::Implementation::Release( SoundSource3D::Implementation* _soundSource3DImpl )
    {
        NANE_ASSERT_R( interface != NULL, "SoundSystem must be initialized" );
        NANE_ASSERT_R( this == _soundSource3DImpl->creator, "SoundSource3D must be valid" );
        ISoundSource3D* soundSource3DInterface = static_cast<ISoundSource3D*>(_soundSource3DImpl->interface);
        delete _soundSource3DImpl;
        interface->ReleaseSoundSource(soundSource3DInterface);
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
}   // namespace nane
